package com.yuri.platform.utils.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.regex.Pattern;

/*
 * 用于文件类型检查，通过文件16进制头信息判断文件类型
 * */
public class FileTypeCheck {

    private String headerHexString;

    private FileTypeEnum fileType;

    public String getHeaderHexString() {
        return headerHexString;
    }

    public void setHeaderHexString(String headerHexString) {
        this.headerHexString = headerHexString;
    }

    public FileTypeEnum getFileType() {
        return fileType;
    }

    public void setFileType(FileTypeEnum fileType) {
        this.fileType = fileType;
    }

    // 目前读取10字节头信息，对应长度20的16进制字符串
    private static final int headerLength = 8;
    /* @Deprecated */
    private static final HashMap<String, FileTypeEnum> typeEnumMap = new HashMap<String, FileTypeEnum>() {{
        System.out.println("文件枚举类型Map构造函数");
        for (FileTypeEnum typeEnum : FileTypeEnum.values()) {
            put(typeEnum.getHexHeader(), typeEnum);
        }
    }};

    // 构造函数，初始化，其他构造函数必须调用
    public FileTypeCheck() {
    }

    // 构造函数，
    public FileTypeCheck(File file) {
        // 调用此对象无参构造函数
        this();
        this.headerHexString = this.transToHexString(file);
        this.fileType = this.typeCheck();
    }

    /*
     * 获取文件2进制头的16进制字符串
     * 一个字节8个2进制数，16进制最大为FF，最小为0
     * 16进制文件头 每一个字节对应长度为2的16进制字符串，长度不足2的用0补充
     * */
    private String byteToHexString(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        if (bytes == null || bytes.length < 1) {
            return "";
        }
        // 循环处理传入的字节
        for (byte eachByte : bytes) {
            int hexValue = eachByte & 0xFF;
            String hexString = Integer.toHexString(hexValue);
            // 每个字节对应长度为2的字符串，不足的用0补足
            if (hexString.length() < 2) {
                builder.append(0);
            }
            builder.append(hexString);
        }
        return builder.toString().toUpperCase();
    }

    /*
     * 返回16进制字符串
     * */
    private String transToHexString(File file) {
        InputStream inputStream;
        byte[] bytes = new byte[FileTypeCheck.headerLength];
        try {
            inputStream = new FileInputStream(file);
            int streamRead = inputStream.read(bytes, 0, FileTypeCheck.headerLength);
            // 关闭文件流，防止内存泄露
            inputStream.close();
            if (streamRead > 0) {
                return this.byteToHexString(bytes);
            } else {
                return null;
            }
        } catch (IOException e) {
            e.getStackTrace();
            return null;
        }
    }

    private FileTypeEnum typeCheck() {
        String hexString = this.headerHexString;
        if (hexString != null) {
            // 每种文件16进制字符串头信息长度都不一样，因此循环查询Map
            for (int i = 0; i <= 2 * FileTypeCheck.headerLength && i <= hexString.length(); i += 2) {
                String subHexString = hexString.substring(0, i);
                for (FileTypeEnum typeEnum : FileTypeEnum.values()) {
                    if (Pattern.matches(typeEnum.getHexHeader(), subHexString)) {
                        return typeEnum;
                    }
                }
            }
            return FileTypeEnum.NONE;
        } else {
            return FileTypeEnum.ERROR;
        }
    }
}
